select模块主要是用于IO多路复用
select 提供了三个方法:
- select -> window 仅支持select
- poll -> linux可用
- eopll -> linux可用
1. .select()方法
- 三个必传的参数:
- 输入列表 -> 就是IO 中的 I -> 监听输入列表中的内容是否有用户进行了连接(是否有数据返回),一般是监听 sk 和 conn
- 输出列表 -> 就是IO 中的 O
- 错误列表
- .select()方法的返回值是一个元组,元组中包含了输入列表(包含 以被用户连接的sk 或 多个得到数据的conn对象)、输出列表、错误列表
- 使用select实现IO多路复用
# server.py
import socket
import select
sk = socket.socket()
sk.bind(('127.0.0.1', 8080))
sk.listen()
read_lst = [sk] # 输入列表
while True:
rl, wl, xl = select.select(read_lst, [], []) # 监听输入列表中sk或多个conn是否有用户进行连接(是否有数据返回),如果有就会返回一个列表中包含 以被用户连接的sk 或 多个得到数据的conn对象 (因为有多个客户端对服务端进行连接,所以才会有多个conn对象)
for item in rl: # 循环select的返回值中的输入列表,因为里面包含了 以被用户连接的sk 或 多个得到数据的conn对象(因为有多个客户端对服务端进行连接,所以才会有多个conn对象)
if item == sk: # 判断是否是sk对象(因为sk对象只会有一个,并且是同一个),如果等于sk对象那么就代表有新的客户端对服务端进行连接
conn, addr = item.accept() # 得到一个conn客户端对象
read_lst.append(conn) # 将 与服务端进行链接了的客户端对象放入 read_lst 输入列表中
else: # 如果不是sk对象就是conn对象
ret = item.recv(1024).decode('utf-8')
if not ret: # 判断接收到的消息是否为空,如果是就说明客户端已经断开连接这样就关闭该客户端并且从read_lst输入列表中删除,如果不为空就打印该数据并且向客户端回一条消息
item.close()
read_lst.remove(item)
else:
print(ret)
item.send(ret.upper().encode('utf-8'))
# client.py
import socket
import time
from threading import Thread
def fun():
sk = socket.socket()
sk.connect(('127.0.0.1', 8080))
for i in range(10):
time.sleep(2)
sk.send(b'hello')
print(sk.recv(1024))
sk.close()
for i in range(10):
Thread(target=fun).start()